// 玩家位置
var position = {
    x: 0,
    y: 0
}
// 炸弹定时器
var time = new Array(3)
var npcTime=null
// 自生buff
var buff = {
    life: 1,
    power: 0
}
var playerTime = null
// 炸弹位置
var bompPosition = []
// 禁止生成箱子的位置
var cannotArr = [
    [0, 0], [0, 1], [0, 2], [1, 0], [2, 0], [9, 9], [9, 8], [9, 7], [8, 9], [7, 9]
]
// 固定物
var fixArr = []
// 可毁物
var ruinArr = []
// 加生命
var lifeArr = []
// 加威力
var powerArr = []
// 人机
var npcArr = []
// 深拷贝数组
var deepRuin, deepLife, deepPower, deepNPC;
var w, h
// 生成地图
function add(m, n) {
    w = m
    h = n
    for (var i = 0; i < m; i++) {
        for (var j = 0; j < n; j++) {
            $('#content').append('<div class="box" data-X=' + j + ' data-Y=' + i + '></div>')
        }
    }
}
// 深拷贝
function deepCopy(copyArr) {
    var newArr = []
    for (var d = 0; d < copyArr.length; d++) {
        let [...arr] = copyArr[d]
        newArr.push(arr)
    }
    return newArr
}
// npc位置确定
function npcPosition(idx) {
    var npcLeft = 8 + deepNPC[idx][0] * 46 + "px"
    var npcTop = 18 + deepNPC[idx][1] * 46 + "px"
    $(".npc[data-id=" + idx + "]").css("left", npcLeft).css("top", npcTop)
}
// 添加人机
function addNPC() {
    for (var i = 0; i < 5; i++) {
        var x = Math.floor(Math.random() * 10);
        var y = Math.floor(Math.random() * 10);
        // 判断生成位置是否已有障碍物或者为不许生成位置
        if (!detect(x, y, cannotArr) && !detect(x, y, fixArr) && !detect(x, y, ruinArr)) {
            npcArr.push([x, y])
            $("#content").append('<div class="npc" data-id=' + i + '></div>')
        } else {
            i--
        }
    }
    deepNPC = deepCopy(npcArr)
    for (var j = 0; j < deepNPC.length; j++) {
        npcPosition(j)
    }
}
// 二维数组获取下标
function getIndex(x, y, arr) {
    var index = null
    for (var i = 0; i < arr.length; i++) {
        if (arr[i][0] == x && arr[i][1] == y) {
            index = i
            break
        }
    }
    return index
}
// npc移动
function npcMove() {
    npcTime=setInterval(function () {
        for (var i = 0; i < npcArr.length; i++) {
            // 判断玩家是否在npc视野中
            var condition = getVision(npcArr[i][0], npcArr[i][1])
            // 获取npc下标
            var deepIndex = getIndex(npcArr[i][0], npcArr[i][1], deepNPC)
            // 如果玩家不在npc视野内
            if (!condition) {
                var x = npcArr[i][0]
                var y = npcArr[i][1]
                var m = Math.floor(Math.random() * 4)
                if (m == 0) {
                    if (x >= 1 && !npcMoveJudge(x - 1, y)) {
                        npcArr[i][0]--
                        deepNPC[deepIndex][0]--
                    } else {
                        m = 1
                    }
                }
                if (m == 1) {
                    if (x < w - 1 && !npcMoveJudge(x + 1, y)) {
                        npcArr[i][0]++
                        deepNPC[deepIndex][0]++
                    } else {
                        m = 2
                    }
                }
                if (m == 2) {
                    if (y >= 1 && !npcMoveJudge(x, y - 1)) {
                        npcArr[i][1]--
                        deepNPC[deepIndex][1]--
                    } else {
                        m == 3
                    }
                }
                if (m == 3) {
                    if (y < h - 1 && !npcMoveJudge(x, y + 1)) {
                        npcArr[i][1]++
                        deepNPC[deepIndex][1]++
                    } else {
                        m == 0
                    }
                }
            }
            // 玩家在npc视野内 
            else {
                if (condition == "left") {
                    npcArr[i][0]--
                    deepNPC[deepIndex][0]--
                } else if (condition == "right") {
                    npcArr[i][0]++
                    deepNPC[deepIndex][0]++
                } else if (condition == "top") {
                    npcArr[i][1]--
                    deepNPC[deepIndex][1]--
                } else if (condition == "bottom") {
                    npcArr[i][1]++
                    deepNPC[deepIndex][1]++
                }
            }
            npcPosition(deepIndex)
        }
        moveWithNPC()
        compute()
    }, 1000)
}
// 判断玩家是否被npc碰到
function moveWithNPC() {
    var flag = false
    for (var i = 0; i < npcArr.length; i++) {
        if (npcArr[i][0] == position.x && npcArr[i][1] == position.y) {
            flag = true
            break
        }
    }
    // 如果被碰到了
    if (flag) {
        if (!playerTime) {
            buff.life--
            // 玩家还有生命
            if (buff.life) {
                playerTime = setTimeout(function () {
                    clearTimeout(playerTime)
                    playerTime = null
                }, 3000)
                // 回到出生地
                position.x = 0
                position.y = 0
                playerPosition()
            }
        }
    }
}
// 生成盒子
function addBox(ele, arr) {
    for (var i = 0; i < arr.length; i++) {
        $("#content").append('<div class=' + ele + ' data-id=' + i + '></div>')
    }
    $("." + ele).each(function () {
        var ids = $(this).data("id")
        var eleLeft = arr[ids][0]
        var eleTop = arr[ids][1]
        $(this).css("left", 46 * eleLeft + "px").css("top", 10 + 46 * eleTop + "px")
    })
}
// 生成玩家
function player() {
    $('#content').append('<div id="player" class="player"></div>')
    playerPosition()
}
// 玩家位置确认
function playerPosition() {
    $("#player").css("left", 8 + position.x * 46 + "px").css("top", 18 + position.y * 46 + "px");
}
// 检测二维数组是否有某个数组
function detect(x, y, arr) {
    var flag = false
    for (var j = 0; j < arr.length; j++) {
        if (arr[j][0] == x && arr[j][1] == y) {
            flag = true
            break
        }
    }
    return flag
}
// 固定物生成
function addFix() {
    for (var i = 0; i < 10; i++) {
        var x = Math.floor(Math.random() * 10);
        var y = Math.floor(Math.random() * 10);
        if (!detect(x, y, fixArr) && !detect(x, y, cannotArr)) {
            fixArr.push([x, y])
        } else {
            i--
        }
    }
    addBox("fix", fixArr)
}
// 可毁物生成
function addRuin() {
    for (var i = 0; i < 10; i++) {
        var x = Math.floor(Math.random() * 10);
        var y = Math.floor(Math.random() * 10);
        if (!detect(x, y, fixArr) && !detect(x, y, cannotArr) && !detect(x, y, ruinArr)) {
            ruinArr.push([x, y])
        } else {
            i--
        }
    }
    deepRuin = deepCopy(ruinArr)
    addBox("ruin", ruinArr)
}
// 生命buff
function addLife() {
    for (var i = 0; i < 5; i++) {
        lifeArr.push(ruinArr[i])
    }
    deepLife = deepCopy(lifeArr)
    addBox("life", lifeArr)
}
// 威力buff
function addPower() {
    for (var i = 5; i < 10; i++) {
        powerArr.push(ruinArr[i])
    }
    deepPower = deepCopy(powerArr)
    addBox("power", powerArr)
}
// 玩家是否再npc视野内
function getVision(X, Y) {
    var n = 0
    var conditionArr = ["left", "right", "top", "bottom"]
    var condition = null
    // 判断玩家是否在视野内的四个方向之一
    while (n < 4) {
        var nowX = X
        var nowY = Y
        while (true) {
            if (n == 0) {
                nowX--
                if (nowX < 0) {
                    break
                }
            } else if (n == 1) {
                nowX++
                if (nowX == w) {
                    break
                }
            } else if (n == 2) {
                nowY--
                if (nowY < 0) {
                    break
                }
            } else if (n == 3) {
                nowY++
                if (nowY == h) {
                    break
                }
            }
            // 此方向视野被障碍物挡住了
            if (detect(nowX, nowY, fixArr) || detect(nowX, nowY, ruinArr)) {
                break
            }
            // 玩家在视野内
            if (nowX == position.x && nowY == position.y) {
                condition = conditionArr[n]
            }
        }
        n++
    }
    return condition
}
// npc移动位置是否有障碍
function npcMoveJudge(x, y) {
    var flag = false
    for (var i = 0; i < fixArr.length; i++) {
        if (fixArr[i][0] == x && fixArr[i][1] == y) {
            flag = true
            break
        }
    }
    //移动位置是否有可毁物
    if (!flag) {
        for (var j = 0; j < ruinArr.length; j++) {
            if (ruinArr[j][0] == x && ruinArr[j][1] == y) {
                flag = true
                break
            }
        }
    }
    return flag
}
// 判断小球移动位置是否有阻碍物
function moveJudge(x, y) {
    var flag = false
    for (var i = 0; i < fixArr.length; i++) {
        if (fixArr[i][0] == x && fixArr[i][1] == y) {
            flag = true
            break
        }
    }
    //移动位置是否有可毁物
    if (!flag) {
        for (var j = 0; j < ruinArr.length; j++) {
            if (ruinArr[j][0] == x && ruinArr[j][1] == y) {
                flag = true
                break
            }
        }
    }
    // 移动位置是否有生命buff
    if (!flag) {
        for (var i = 0; i < lifeArr.length; i++) {
            if (lifeArr[i][0] == x && lifeArr[i][1] == y) {
                var deepIndex = getIndex(lifeArr[i][0], lifeArr[i][1], deepLife)
                lifeArr.splice(i, 1)
                i--
                $(".life[data-id=" + deepIndex + "]").remove()
                buff.life++;
                show()
            }
        }
    }
    // 移动位置是否有威力buff
    if (!flag) {
        for (var i = 0; i < powerArr.length; i++) {
            if (powerArr[i][0] == x && powerArr[i][1] == y) {
                var deepIndex = getIndex(powerArr[i][0], powerArr[i][1], deepPower)
                powerArr.splice(i, 1)
                i--
                $(".power[data-id=" + deepIndex + "]").remove()
                buff.power++;
                show()
            }
        }
    }
    return flag
}
// 小球移动
function move() {
    $(document).keydown(function (e) {
        switch (e.keyCode) {
            // 向上（w）
            case 87:
                if (position.y > 0) {
                    if (!moveJudge(position.x, position.y - 1)) {
                        position.y--;
                        playerPosition()
                    }
                }
                break;
            // 向下（s）
            case 83:
                if (position.y < h - 1) {
                    if (!moveJudge(position.x, position.y + 1)) {
                        position.y++;
                        playerPosition()
                    }
                }
                break;
            // 向左（a）
            case 65:
                if (position.x > 0) {
                    if (!moveJudge(position.x - 1, position.y)) {
                        position.x--;
                        playerPosition()
                    }
                }
                break;
            // 向右（d）
            case 68:
                if (position.x < w - 1) {
                    if (!moveJudge(position.x + 1, position.y)) {
                        position.x++;
                        playerPosition()
                    }
                }
                break;
            // 放炸弹（空格）
            case 32:
                var ballX = $("#player").css('left')
                var ballY = $("#player").css("top")
                bounce(ballX, ballY, position.x, position.y)
                break;
        }
        moveWithNPC()
        compute()
    })
    
}
// 炸弹爆炸
function bounce(ballLeft, ballTop, X, Y) {
    for (var i = 0; i < time.length; i++) {
        if (!time[i]) {
            // 添加炸弹
            console.log("aaa")
            $("#content").append('<div class="time" data-id=' + i + '></div>')
            $(".time[data-id=" + i + "]").css("left", ballLeft).css("top", ballTop)
            bompPosition.push([X, Y])
            time[i] = setTimeout(function () {
                $(".box[data-X=" + X + "][data-Y=" + Y + "]").addClass("timeBounce")
                var n = 0
                // 向炸弹的四个方向添加爆炸样式
                while (n < 4) {
                    var nowX = X
                    var nowY = Y
                    var condition = "LeftBounce"
                    for (var l = 0; l <= buff.power; l++) {
                        if (n == 0) {
                            nowX--
                            if (nowX < 0) {
                                break
                            }
                            condition = "LeftBounce"
                        } else if (n == 1) {
                            nowX++
                            if (nowX == w) {
                                break
                            }
                            condition = 'RightBounce'
                        } else if (n == 2) {
                            nowY--
                            if (nowY < 0) {
                                break
                            }
                            condition = "TopBounce"
                        } else {
                            nowY++
                            if (nowY == h) {
                                break
                            }
                            condition = "BottomBounce"
                        }
                        // 添加动画位置没有固定物
                        if (!detect(nowX, nowY, fixArr)) {
                            $(".box[data-X=" + nowX + "][data-Y=" + nowY + "]").addClass("time" + condition)
                            // 添加动画位置有可毁物
                            if (detect(nowX, nowY, ruinArr)) {
                                break
                            }
                        } else {
                            break
                        }
                    }
                    n++
                }
                judge()
                // 三秒后移除样式
                setTimeout(function () {
                    // 计算
                    compute()
                    // 移除炸弹
                    $("#content").children(".time[data-id=" + i + "]").remove()
                    $(".box").removeClass("timeBounce").removeClass("timeLeftBounce").removeClass("timeRightBounce").removeClass("timeTopBounce").removeClass("timeBottomBounce")
                    clearTimeout(time[i])
                    time[i] = null
                }, 200)
            }, 3000)
            break
        }
    }
}
// 判断炸弹爆炸是否触碰
function collision(x, y) {
    // 炸弹坐标
    var bounceX = bompPosition[0][0]
    var bounceY = bompPosition[0][1]
    var flagX = bounceX
    var flagY = bounceY
    for (var i = 0; i <= buff.power + 1; i++) {
        // 检测坐标的x与炸弹坐标的x一致
        if (x == bounceX) {
            // 从炸弹坐标向四周扩散计算
            // 当前坐标为可毁物坐标而且并非是要检测的坐标，炸弹只能穿透一个可毁物
            if (detect(x, flagY, judgeArr) && flagY != y) {
                return false
            }
            // 当前坐标为固定物坐标，炸弹无法穿透
            if (detect(x, flagY, fixArr)) {
                return false
            }
            //  当前坐标为可毁物坐标而且是要检测的坐标
            else if (detect(x, flagY, judgeArr) && flagY == y) {
                return true
            } 
            // 当前坐标不是可毁物坐标但是为要检测的坐标
            else if (!detect(x, flagY, judgeArr) && flagY == y) {
                return true
            }
            else {
                // 向上计算
                if (y <= bounceY) {
                    flagY--
                }
                // 向下计算
                else {
                    flagY++
                }
            }
        }
        // 检测坐标的y与炸弹坐标的y一致
        else if (y == bounceY) {
            // 当前坐标为可毁物坐标而且并非是要检测的坐标，炸弹只能穿透一个可毁物
            if (detect(flagX, y, judgeArr) && flagX != x) {
                return false
            }
            // 当前坐标为固定物坐标，炸弹无法穿透
            if (detect(flagX, y, fixArr) && flagX != x) {
                return false
            }
            //  当前坐标为可毁物坐标而且是要检测的坐标
            else if (detect(flagX, y, judgeArr) && flagX == x) {
                return true
            } 
            // 当前坐标不是可毁物坐标但是为要检测的坐标
            else if (!detect(flagX, y, judgeArr) && flagX == x) {
                return true
            }
            else {
                if (x <= bounceX) {
                    flagX--
                } else {
                    flagX++
                }
            }
        }
    }
}
// 触碰
function judge() {
    var playerX = position.x
    var playerY = position.y
    // 可毁物被炸
    // 深拷贝每一次爆炸前存在的可毁物数组以防穿透可毁物
    judgeArr = deepCopy(ruinArr)
    for (var i = 0; i < ruinArr.length; i++) {
        // 可毁物被炸
        if (collision(ruinArr[i][0], ruinArr[i][1])) {
            var deepIndex = getIndex(ruinArr[i][0], ruinArr[i][1], deepRuin)
            ruinArr.splice(i, 1)
            i--
            $(".ruin[data-id=" + deepIndex + "]").remove()
        }
    }
    // palyer1被炸到
    if (collision(playerX, playerY)) {
        // 当前不为玩家无敌时间
        if (!playerTime) {
            buff.life--;
            // 玩家还有生命
            if (buff.life) {
                playerTime = setTimeout(function () {
                    clearTimeout(playerTime)
                    playerTime = null
                }, 3000)
                // 回到出生地
                position.x = 0
                position.y = 0
                playerPosition()
            }
        }
    }
    // npc
    for (var n = 0; n < npcArr.length; n++) {
        // npc被炸
        if (collision(npcArr[n][0], npcArr[n][1])) {
            var deepIndex = getIndex(npcArr[n][0], npcArr[n][1], deepNPC)
            npcArr.splice(n, 1)
            n--
            $(".npc[data-id=" + deepIndex + "]").remove()
        }
    }
    // 炸弹数组删除元素
    bompPosition.splice(0, 1)
    // 下方数据实时更新
    show()
}
// 下方数据
function show() {
    $(".playerLife").text("life:" + buff.life)
    $(".playerPower").text("power:" + buff.power)
}
// 清除炸弹定时器
function clearTime() {
    for (var i = 0; i < time.length; i++) {
        clearTimeout(time[i])
    }
}
// 计算结果
function compute() {
    if (!buff.life) {
        clearTime()
        clearInterval(npcTime)
        alert("Game Over")
        alert("重新开始")
        window.location.reload()
    }
    if(!npcArr.length){
        clearTime()
        clearInterval(npcTime)
        alert('玩家胜利')
        alert('重新开始')
        window.location.reload()
    }
}
// 地图
add(10, 10)
// 固定物
addFix()
// 可毁物
addRuin()
// 生命buff
addLife()
// 威力buff
addPower()
// npc
addNPC()
// 玩家
player()
// 玩家移动
move()
// npc移动
npcMove()
// 下方数据显示
show()